package me.ingxin.android.router.route

import android.net.Uri
import me.ingxin.android.router.Store
import me.ingxin.android.router.utils.Logger

/**
 * Created by ingxin on 2022/4/25
 */
class AnyLoader internal constructor(private val uri: Uri) {

    /**
     * 实例化一个对象
     * @param parameter 构造函数对应的参数
     */
    fun newInstance(vararg parameter: Any?): Any? {
        val path = uri.path
        if (path == null) {
            Logger.e("route path is null!")
            return null
        }
        val meta = Store.instance.getAllRoute()[path]
        if (meta == null) {
            Logger.e("route path not found")
            return null
        }
        return getInstance(meta.destination, parameter)
    }

    private fun getInstance(clazz: Class<*>, params: Array<out Any?>): Any? {
        try {
            if (params.isEmpty()) {
                return clazz.newInstance()
            }
            //遍历找到适合的构造函数
            for (constructor in clazz.constructors) {
                val classes = constructor.parameterTypes
                if (isParameterTypeMatch(classes, params)) {
                    return constructor.newInstance(*params)
                }
            }
        } catch (ex: Exception) {
            ex.printStackTrace()
        }
        Logger.e("no match constructor and return null")
        return null
    }

    /**
     * 判断输入的参数是否和构造函数的参数类型匹配
     */
    private fun isParameterTypeMatch(target: Array<Class<*>>, params: Array<out Any?>): Boolean {
        if (target.size != params.size) {
            return false
        }
        for ((i, host) in target.withIndex()) {
            //输入的参数类型
            val client = params[i]?.javaClass
            Logger.d("expect = ${host.name}, input = ${client?.name}")
            val typeMatch = if (client == null) {
                //输入为null，那么构造函数的参数不能为基础类型(boolean,char,byte,short,int,float,long,double,void)
                !host.isPrimitive
            } else {
                host == client || host.isAssignableFrom(client)
                        || transform(host) == transform(client)
            }
            if (!typeMatch) {
                return false
            }
        }
        return true
    }

    /**
     * 因为java自动装箱拆箱，将类型都转化成java包装类统一判断
     */
    private fun transform(clz: Class<*>): Class<*> {
        return when (clz) {
            Byte::class.java -> Byte::class.javaObjectType
            Short::class.java -> Short::class.javaObjectType
            Int::class.java -> Int::class.javaObjectType
            Long::class.java -> Long::class.javaObjectType
            Float::class.java -> Float::class.javaObjectType
            Double::class.java -> Double::class.javaObjectType
            Char::class.java -> Char::class.javaObjectType
            Boolean::class.java -> Boolean::class.javaObjectType
            else -> clz
        }
    }

}